Tim_ATmega328p.c
#include "Tim_ATmega328p.h"
/* Setting period of simple continuous interrupts for a chosen Timer
* Timer (TIM0, TIM1, TIM2)
* Mode - Mode of how the Timer works (PWM, OVERFLOW_INT, ADC_TRIGGERING)
* Period_us - Period for PWM or interrupt generation
*/
my_bool TIMER_Set(tim_t Timer, tim_mode_t Mode, unsigned long Period_us)
{
switch(Timer)
{
case TIM0: // For AVR MCUs - 8 Bit Timer
{
switch(Mode)
{
case PWM:
{
}break;
case OUT_COMP_A:
{
}break;
default: ;//Serial.println("The mode of TIM2 is still not handled in this version");
} // switch(Mode)
} break; // case TIM0
case TIM1: // For AVR MCUs - 16 Bit Timer
{
switch(Mode)
{
case OUT_COMP_A:
{
} break; // case OVERFLOW_INT
case PWM: // PWM for the channel A (experimental) Fast PWM, 10-bit, TOP = 0x03FF, PWM Pin - PB1 (Arduino D9)
{
// Here - Period_us = PWM Duty Cycle
// F_PWM = F_CPU / (psc * (1 + 0x03FF))
TCCR1A |= (1<<COM1A1) | (1<<WGM11) | (1<<WGM10);
TCCR1B |= (1<<WGM12);
TIMSK1 |= (1<<TOIE1); // Enable Timer 1 overflow interrupt
// Prescaler = 0, PWM Period = 15625 Hz
if(Period_us > 100)
{
Period_us = 100;
}
OCR1A = (0x03FF * Period_us / 100);
TCCR1B |= (1<<CS10); // Start timer
} break;
default: ;//Serial.println("The mode of TIM2 is still not handled in this version");
} // switch(Mode), TIM 1
} break; // case TIM1
case TIM2: // For AVR MCUs - 8 Bit Timer
{
switch(Mode)
{
case TIM2_A_SOUND_PWM: // the following setting is made for the "Intercom" project. Setting is made for the same frequency as ADC Triggering. the commented section - for a free project.
{
/**************** Chosen PWM Mode is "Fast PWM" using Channel A with top on 0xFF (bits WGM22..WGM20 = 3 = 0b011) ****************/
/* /\ /\
* / \/ \/
* _|¯|_|¯|_
*/
TCCR2A |= (1<<COM2A1) | (1<<WGM21) | (1<<WGM20); // COM2A1-COM2A0 = 10: Non inverting
// WGM22-WGM20 = 011: Fast PWM 8-bit
// fOC1PWM = f_CPU / (N * (1 + TOP)); Where N is Prescaler and TOP is 0xff in the chosen mode
TCNT2 = 0;
OCR2A = 0; // No default PWM frequency
TIMSK2 |= (1<<TOIE2); // Enable Timer 2 overflow interrupt
TCCR2B |= (1<<CS20) ; // Start Timer 2 (prescaler = 1)
} break; // case TIM2_CHA_SOUND_PWM
case OUT_COMP_A:
{
uint16_t prescaler = set_TIM2_prescaler(Period_us, Mode);
uint16_t Ticks_required;
Ticks_required = F_CPU/prescaler/1e6*Period_us-1;
OCR2A = (uint8_t)Ticks_required;
TIMSK2=(1<<OCF2A); // Beginning of TIM2 COMP_A overflow interrupts
//Serial.println("\nPrescaler of TIM2: " + (String)prescaler);
//Serial.println("Ticks required: " + (String)Ticks_required);
} break; // case OVERFLOW_INT:
default: ;//Serial.println("The mode of TIM2 is still not handled in this version");
} // switch(Mode)
} break; // case TIM2;
} // switch(Timer)
return HIGH;
}
/* Setting the PWM Value for the TIM1, set in a 10 bit Fast PWM Mode
*/
void TIM1_Set_PWM(uint8_t Duty_PWM)
{
OCR1A = ((long)0x03FF * Duty_PWM / 100);
}
/* Calculating the prescaler for the Timer
* Arguments:
* Period us - period value counted in us
* Mode - mode of Timer work
*/
uint16_t set_TIM2_prescaler(unsigned long Period_us, tim_mode_t Mode)
{
/***************** Setting the CS20..CS22 prescaler Bits in TCCR2B Register ****************/
/*
* The prescaler setting is set to the highest precision but the highest amount of timer ticks
* to reduse the precision and decrease the amount of ticks - delete the "else's" after "if's"
*/
uint16_t prescaler = 0;
switch(Mode)
{
case OUT_COMP_A:
{
if(Period_us > 16320) // 16320 us is the highehst value for the 8Bit Timer 2
{
//Serial.println("TIM2 Period too high. Breakdown");
return LOW;
}
if((Period_us >= 1) && (Period_us < 15)) // Then needed Prescaler = 1 (no Prescaling)
{
TCCR2B |= (1<<CS20);
prescaler = 1;
} else
if((Period_us >= 1) && (Period_us < 126)) // Then needed Prescaler = 8
{
TCCR2B |= (1<<CS21);
prescaler = 8;
} else
if((Period_us >= 2) && (Period_us < 510)) // Then needed Prescaler = 32 // interruptions occur too slow with this Prescaler. reason unknown
{
TCCR2B |= (1<<CS20) | (1<<CS21);
prescaler = 32;
} else
if((Period_us >= 4) && (Period_us < 1020)) // Then needed Prescaler = 64
{
TCCR2B |= (1<<CS22);
prescaler = 64;
} else
if((Period_us >= 8) && (Period_us < 2040)) // Then needed Prescaler = 128
{
TCCR2B |= (1<<CS20) | (1<<CS22);
prescaler = 128;
} else
if((Period_us >= 16) && (Period_us < 4080)) // Then needed Prescaler = 256
{
TCCR2B |= (1<<CS21) | (1<<CS22);
prescaler = 256;
} else
if((Period_us >= 64) && (Period_us <= 16320)) // Then needed Prescaler = 1024
{
TCCR2B |= (1<<CS20) | (1<<CS21) | (1<<CS22);
prescaler = 1024;
}
} break; // case OVERFLOW_INT
default:
{
//Serial.println("Chosen mode for TIM2 Prescaler setting is still not implemented.");
}
} // switch(Mode)
return prescaler;
}